package utiljava.image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

/**
 * 实现向图片加水印，图片或者文字
 *
 * @author Liu Yulong
 */
public final class WaterMarkUtil {
	public static final int RIGHT_DOWN = 1; // 右下角
	public static final int RIGHT_UP = 2; // 右上角
	public static final int LEFT_DOWN = 3; // 左下角
	public static final int LEFT_UP = 4; // 左上角
	public static final int CENTER = 5; // 中间
	/**
	 * 默认的水印透明度（百分比）
	 */
	private static final float DEFAULT_WATERMARK_TRANSPARENCY = 0.5F;

	public WaterMarkUtil() {
	}

	/**
	 * @param waterImg
	 *            水印文件
	 * @param srcImg
	 *            源文件
	 * @param outImg
	 *            目标文件
	 * @param position
	 *            水印位置（如WaterMarkUtil.RIGHT_DOWN）
	 * @param transparency
	 *            水印透明度（0f～1f）
	 */
	public final static void waterImage(String waterImg, String srcImg, String outImg, int position, float transparency) {
		try {
			File sourceFile = new File(srcImg);
			File waterFile = new File(waterImg);
			Image waterImage = ImageIO.read(waterFile);
			int wideth_biao = waterImage.getWidth(null);
			int height_biao = waterImage.getHeight(null);

			Image sourceImage = ImageIO.read(sourceFile);
			int width = sourceImage.getWidth(null);
			int height = sourceImage.getHeight(null);
			if (width < wideth_biao || height < height_biao) {// 小图片不加水印
				FileOutputStream out = new FileOutputStream(outImg);
				byte[] data = fileToStream(sourceFile);
				BufferedOutputStream fout = null;
				ByteArrayInputStream in = new ByteArrayInputStream(data);
				try {
					byte[] b = new byte[1024 * 10];
					fout = new BufferedOutputStream(out);
					while (in.read(b) > 0) {
						out.write(b);
					}
					out.flush();
					out.close();
					in.close();
				} catch (Exception e) {
					e.printStackTrace();
					throw e;
				} finally {
					if (in != null) {
						in.close();
					}
					if (fout != null) {
						fout.close();
					}
				}
				return;
			}
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = image.createGraphics();
			g.drawImage(sourceImage, 0, 0, width, height, null);

			//默认右下角
			int x = width - waterImage.getWidth(null);
			int y = height - waterImage.getHeight(null);
			if (position == WaterMarkUtil.CENTER) {
				x = (width - wideth_biao) / 2;
				y = (height - height_biao) / 2;
			} else if (position == WaterMarkUtil.RIGHT_UP) {
				x = width - waterImage.getWidth(null);
				y = 0;
			} else if (position == WaterMarkUtil.LEFT_DOWN) {
				x = 0;
				y = height - waterImage.getHeight(null);
			} else if (position == WaterMarkUtil.LEFT_UP) {
				x = 0;
				y = 0;
			}

			// 设置图片透明度
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
			// 图片右下角添加
			g.drawImage(waterImage, x, y, null);

			g.dispose();
			/*FileOutputStream out = new FileOutputStream(outImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
			param.setQuality(80f, true);
			encoder.encode(image);
			out.close();*/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 打印文字水印图片
	 *
	 * @param text
	 *            水印文字
	 * @param srcImg
	 *            原图
	 * @param outImg
	 *            目标图
	 * @param fontName
	 *            字体名称
	 * @param fontStyle
	 *            字体风格
	 * @param color
	 *            字体颜色
	 * @param fontSize
	 *            字体大小
	 * @param position
	 *            水印位置（如WaterMarkUtil.RIGHT_DOWN）
	 * @param transparency
	 *            水印透明度（0f～1f）
	 */
	public static void waterText(String text, String srcImg, String outImg, String fontName, int fontStyle,
			Color color, int fontSize, int position, float transparency) {
		try {
			File sourceFile = new File(srcImg);
			Image src = ImageIO.read(sourceFile);
			int width = src.getWidth(null);
			int height = src.getHeight(null);
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = image.createGraphics();
			g.drawImage(src, 0, 0, width, height, null);
			g.setColor(color);
			Font font = new Font(fontName, fontStyle, fontSize);
			FontMetrics metrics = g.getFontMetrics(font);
			int stringWidth = metrics.stringWidth(text);
			int fontHeight = metrics.getHeight();
			g.setFont(font);

			//默认右下角
			int x = width - stringWidth;
			int y = height - fontHeight;
			if (position == WaterMarkUtil.CENTER) {
				x = (width - stringWidth) / 2;
				y = (height - fontHeight) / 2;
			} else if (position == WaterMarkUtil.RIGHT_UP) {
				x = width - stringWidth;
				y = 0;
			} else if (position == WaterMarkUtil.LEFT_DOWN) {
				x = 0;
				y = height - fontHeight;
			} else if (position == WaterMarkUtil.LEFT_UP) {
				x = 0;
				y = 0;
			}

			// 设置透明度
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
			g.drawString(text, x, y + fontHeight);

			g.dispose();
			/*FileOutputStream out = new FileOutputStream(outImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
			param.setQuality(80f, true);
			encoder.encode(image);
			out.close();*/
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e);
		}
	}

	/**
	 * 将文件对象转成字节流
	 *
	 * @param file
	 * @return
	 * @throws IOException
	 */
	private static byte[] fileToStream(File file) throws IOException {
		BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		final int BUFSIZ = 1024;
		byte inbuf[] = new byte[BUFSIZ];
		int n;
		while ((n = input.read(inbuf, 0, BUFSIZ)) != -1)
			output.write(inbuf, 0, n);
		input.close();
		output.close();
		return output.toByteArray();
	}

	/**
	 * 向图片上添加水印字符
	 *
	 * @param source
	 * @param watermarkImage
	 * @param watermarkLayout
	 * @return
	 */
	public static BufferedImage watermark(BufferedImage source, BufferedImage watermarkImage, WatermarkLayout layout) {
		return watermark(source, watermarkImage, layout, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	/**
	 * 向图片上添加水印字符
	 *
	 * @param source
	 * @param watermarkImage
	 * @param layout
	 * @param transparency 透明度
	 * @return
	 */
	public static BufferedImage watermark(BufferedImage source, BufferedImage watermarkImage, WatermarkLayout layout,
			float transparency) {
		Point position = computeWatermarkPosition(source, watermarkImage.getWidth(), watermarkImage.getHeight(), layout);
		return watermark(source, watermarkImage, position, transparency);
	}

	public static BufferedImage watermark(BufferedImage source, BufferedImage watermarkImage, Point position) {
		return watermark(source, watermarkImage, position, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	public static BufferedImage watermark(BufferedImage source, BufferedImage watermarkImage, Point position,
			float transparency) {
		if (source == null)
			return null;
		if (watermarkImage == null || position == null)
			return source;
		else {
			Graphics2D g2d = (Graphics2D) source.getGraphics();
			AlphaComposite alpha = AlphaComposite.getInstance(3, transparency);
			g2d.setComposite(alpha);
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2d.drawImage(watermarkImage, position.x, position.y, watermarkImage.getWidth(),
					watermarkImage.getHeight(), null);
			g2d.dispose();
			return source;
		}
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont,
			WatermarkLayout layout) {
		return watermark(source, watermarkText, textFont, Color.white, layout, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont, Color textColor,
			WatermarkLayout layout) {
		return watermark(source, watermarkText, textFont, textColor, layout, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont, Color textColor,
			WatermarkLayout layout, float transparency) {
		if (source == null)
			return null;
		if (watermarkText == null || watermarkText.equals(""))
			return source;
		else {
			Graphics2D g2d = (Graphics2D) source.getGraphics();
			AlphaComposite alpha = AlphaComposite.getInstance(3, transparency);
			g2d.setComposite(alpha);
			g2d.setColor(textColor);
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2d.setFont(textFont);
			FontMetrics fontMetrics = g2d.getFontMetrics();
			Rectangle2D rect = fontMetrics.getStringBounds(watermarkText, g2d);
			Point position = computeWatermarkPosition(source, (int) rect.getWidth(), (int) rect.getHeight(), layout);
			g2d.drawString(watermarkText, position.x, position.y + (int) rect.getHeight());
			g2d.dispose();
			return source;
		}
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont, Point position) {
		return watermark(source, watermarkText, textFont, Color.WHITE, position, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont, Color textColor,
			Point position) {
		return watermark(source, watermarkText, textFont, textColor, position, DEFAULT_WATERMARK_TRANSPARENCY);
	}

	public static BufferedImage watermark(BufferedImage source, String watermarkText, Font textFont, Color textColor,
			Point position, float transparency) {
		if (source == null)
			return null;
		if (watermarkText == null || watermarkText.equals(""))
			return source;
		else {
			Graphics2D g2d = (Graphics2D) source.getGraphics();
			AlphaComposite alpha = AlphaComposite.getInstance(3, transparency);
			g2d.setComposite(alpha);
			g2d.setColor(textColor);
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2d.setFont(textFont);
			FontMetrics fontMetrics = g2d.getFontMetrics();
			Rectangle2D rect = fontMetrics.getStringBounds(watermarkText, g2d);
			g2d.drawString(watermarkText, position.x, position.y + (int) rect.getHeight());
			g2d.dispose();
			return source;
		}
	}

	private static Point computeWatermarkPosition(BufferedImage source, int width, int height, WatermarkLayout layout) {
		if (source == null)
			return null;
		int sourceWidth = source.getWidth();
		int sourceHeight = source.getHeight();
		int px = 0;
		int py = 0;
		if (WatermarkLayout.BOTTOM_LEFT.is(layout)) {
			px = 0;
			py = sourceHeight - height;
		} else if (WatermarkLayout.BOTTOM_CENTER.is(layout)) {
			px = sourceWidth / 2 - width / 2;
			py = sourceHeight - height;
		} else if (WatermarkLayout.BOTTOM_RIGHT.is(layout)) {
			px = sourceWidth - width;
			py = sourceHeight - height;
		} else if (WatermarkLayout.MIDDLE_LEFT.is(layout)) {
			px = 0;
			py = sourceHeight / 2 - height / 2;
		} else if (WatermarkLayout.MIDDLE_CENTER.is(layout)) {
			px = sourceWidth / 2 - width / 2;
			py = sourceHeight / 2 - height / 2;
		} else if (WatermarkLayout.MIDDLE_RIGHT.is(layout)) {
			px = sourceWidth - width;
			py = sourceHeight / 2 - height / 2;
		} else if (WatermarkLayout.TOP_LEFT.is(layout)) {
			px = 0;
			py = 0;
		} else if (WatermarkLayout.TOP_CENTER.is(layout)) {
			px = sourceWidth / 2 - width / 2;
			py = 0;
		} else if (WatermarkLayout.TOP_RIGHT.is(layout)) {
			px = sourceWidth - width;
			py = 0;
		}
		return new Point(px, py);
	}

	public enum WatermarkLayout {
		BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT, MIDDLE_CENTER, MIDDLE_LEFT, MIDDLE_RIGHT, TOP_CENTER, TOP_LEFT, TOP_RIGHT;
		public boolean is(WatermarkLayout t) {
			return ordinal() == t.ordinal();
		}
	}

	public static void main(String[] args) {
		// waterImage("d:/logo.png", "d:/01.jpg", "d:/sss.jpg",WaterMarkUtil.CENTER,0.5f);
		waterText("UCAP.COM.CN", "c:/default.jpg", "c:/default56.jpg", "Dialog", Font.PLAIN, Color.BLACK, 16,
				WaterMarkUtil.RIGHT_DOWN, 1.0f);
	}

}
